package sample.server;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.Properties;
import sample.client.ClientManagerService;
import sample.shared.result.Client;
import sample.shared.result.FileInfo;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
@Singleton
public class ClientManagerServiceImpl extends RemoteServiceServlet implements
		ClientManagerService {
	private String clientRootDir;
	private String title;

	/**
	 * Escape an html string. Escaping data received from the client helps to
	 * prevent cross-site script vulnerabilities.
	 * 
	 * @param html
	 *            the html string to escape
	 * @return the escaped string
	 */
	String escapeHtml(String html) {
		if (html == null) {
			return null;
		}
		return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
				.replaceAll(">", "&gt;");
	}

	@Inject
	public ClientManagerServiceImpl(@Named("title") String title,
			@Named("dir.clientroot") String clientRootDir) {
		super();
		this.title = title;
		this.clientRootDir = clientRootDir;
	}

	public static File getFileFromCode(String clientRootDir, String clientCode) {
		String partnerCode = clientCode.replaceFirst("[0-9]+", "");
		File retval = new File(clientRootDir + File.separator + partnerCode
				+ File.separator + clientCode);
		return retval;
	}

	private void addFiles(File f, String code, String relPath,
			ArrayList<FileInfo> files, int depth) {
		if (f.isFile()) {
			files.add(new FileInfo(code, relPath, f.getName()));
			return;
		} else {
			String path = relPath + File.separator + f.getName();
			File[] childFiles = f.listFiles();
			for (File cf : childFiles) {
				if (depth + 1 < 3)
					addFiles(cf, code, path, files, depth + 1);
			}
		}
	}

	private Properties loadProperties(String propFile) {
		Properties properties = new Properties();

		URL url = BootstrapListener.class.getResource(propFile);
		try {
			properties.load(url.openStream());
		} catch (IOException e) {
			e.printStackTrace();
		}

		return properties;
	}

	@Override
	public ArrayList<Client> getAllClients() throws IllegalArgumentException {
		ArrayList<Client> retval = new ArrayList<Client>();

		Properties clientProps = loadProperties("clients");
		for (Entry<Object, Object> entry : clientProps.entrySet()) {
			String code = entry.getKey().toString();
			String name = entry.getValue().toString();
			File clientDir = getFileFromCode(clientRootDir, code);
			if (clientDir.exists()) {
				retval.add(new Client(name, code));
			}
			else {
				retval.add(new Client(name, "MISSING-CODE-"+code));
			}
		}

		Collections.sort(retval, new Comparator<Client>() {
			@Override
			public int compare(Client a, Client b) {
				return a.getName().compareTo(b.getName());
			}
		});

		return retval;
	}

	@Override
	public ArrayList<FileInfo> getFiles(Client c) {
		File clientDir = getFileFromCode(clientRootDir, c.getCode());
		if (!clientDir.exists())
			return new ArrayList<FileInfo>();
		
		ArrayList<FileInfo> retval = new ArrayList<FileInfo>();
		File[] childFiles = clientDir.listFiles();
		for (File cf : childFiles)
			addFiles(cf, c.getCode(), "", retval, 1);

		Collections.sort(retval, new Comparator<FileInfo>() {
			@Override
			public int compare(FileInfo o1, FileInfo o2) {
				return o1.getName().compareToIgnoreCase(o2.getName());
			}
		});
		return retval;
	}

	@Override
	public String getTitle() {
		return title;
	}
}
